/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.myapp.model.DAO.Exercise;

import com.myapp.model.DAO.HibernateUtil;
import com.myapp.model.ejercicios.Ejercicios;
import com.myapp.model.estados.Estados;
import com.myapp.model.notificaciones.Notificaciones;
import com.myapp.model.resueltos.Resueltos;
import com.myapp.model.temas.Temas;
import com.myapp.model.usuarios.Usuarios;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

/**
 *
 * @author jaime
 */
public class ExerciseDao {

    /**
     * La siguiente consulta nos mostrara el listado de ejercicios
     * propuestos segun el tema seleccionado y siempre que el usuario
     * que lo ha propuesto tenga disponibilidad para corregir dicho enunciado.
     * @param String idTema, Usuarios usr
     * @return List
     */
    public List listarPorTema(String idTema, Usuarios usr) {
        List listEjercicio = null;
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();

        try {
            session.beginTransaction();
            /*
             * listEjercicio = session.createCriteria(Ejercicios.class).
             * add(Restrictions.eq("temas.idtema", idTema)).
             * add(Restrictions.gt("usuarios.dispcorregir",0)).list();
             * session.getTransaction().commit();
             */
            listEjercicio = session.createQuery("from Ejercicios as e where "
                    + "e.temas.idtema=" + idTema + "and e.usuarios.dispcorregir >" + 0 + " and e.usuarios.idusuario!=" + usr.getIdusuario()).list();
        } catch (HibernateException err) {
            System.out.println(err);

            session.getTransaction().rollback();
        }

        return listEjercicio;
    }

    /**
     * Consulta que nos trae la informacion de un ejercicio concreto
     * ademas de todos sus comentarios. Los comentarios vienen dados en
     * forma de un HashSet que deberemos recorrer. La llamada a
     * LEFT_JOIN nos traera el ejercicio tenga o no comentarios. En caso
     * que no tenga comentarios el HashSet tendra valor null.
     * @param String idejercicio
     * @return Ejercicios
     */
    public Ejercicios listarPorId(String idejercicio) {
        Ejercicios ejer = null;
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        try {
            session.beginTransaction();
            ejer = (Ejercicios) session.createCriteria(Ejercicios.class).
                    createAlias("usuarios", "us", CriteriaSpecification.LEFT_JOIN).
                    createAlias("comentarioses", "c", CriteriaSpecification.LEFT_JOIN).
                    add(Restrictions.eq("idejercicio", Integer.valueOf(idejercicio))).uniqueResult();
            session.getTransaction().commit();

        } catch (HibernateException err) {
            session.getTransaction().rollback();
        }
        return ejer;
    }

    /**
     * Metodo que actualiza el estado del ejercicio a Reportado 
     * @param Ejercicios ejer, Usuarios usr
     */
    public void reportar(Ejercicios ejer, Usuarios usr) {//usr es el usuario que ha reportado el ejercicio.
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        Estados est = new Estados();
        byte e = 5;//Estado de "Reportado" en la tabla estados de la base de datos
        est.setIdestado(e);
        ejer.setEstados(est);

        try {
            session.beginTransaction();
            session.update(ejer);
            session.getTransaction().commit();

        } catch (HibernateException err) {
            session.getTransaction().rollback();
        }
    }

    /**
     * Metodo que nos trae la informacion de un ejercicio resuelto por id
     * @param String idResueltos
     * @return Resueltos
     */
    public Resueltos selectExercResolvePorId(String idResueltos) {
        Resueltos ejerResolve = null;
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        try {
            session.beginTransaction();
            ejerResolve = (Resueltos) session.createCriteria(Resueltos.class).
                    createAlias("usuarios", "us", CriteriaSpecification.LEFT_JOIN).
                    createAlias("ejercicios", "ej", CriteriaSpecification.LEFT_JOIN).
                    createAlias("ej.usuarios", "ejusu", CriteriaSpecification.LEFT_JOIN).
                    add(Restrictions.eq("idresueltos", Integer.valueOf(idResueltos))).uniqueResult();
            session.getTransaction().commit();

        } catch (HibernateException err) {
            session.getTransaction().rollback();
        }
        return ejerResolve;
    }

    /**
     * Pasamos un ejercicio seleccionado a la tabla resuelto de la base de datos
     * @param Resueltos resolve 
     */
    public void selectExercToResolve(Resueltos resolve) {

        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        Estados est = new Estados();
        byte e = 12;//Estado de "Elegido" en la tabla estados de la base de datos
        est.setIdestado(e);
        resolve.setEstados(est);
        try {
            session.beginTransaction();
            session.save(resolve);
            session.getTransaction().commit();
        } catch (Exception ex) {
            ex.printStackTrace();
            session.getTransaction().rollback();
        }
    }

    /**
     * Metodo que actualiza el estado de un ejercicio resuelto a Mandado
     * @param Resueltos result contiene el ejercicio resuelto
     * @return Resueltos devuelve el ejercicio resuelto o null si ha habido un error
     */
    public Resueltos resolveExercice(Resueltos result) {

        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        Estados est = new Estados();
        byte e = 9;//Estado de "Mandado" para que lo corriga el autor
        est.setIdestado(e);
        result.setEstados(est);
        try {
            session.beginTransaction();
            session.update(result);
            session.getTransaction().commit();
        } catch (Exception ex) {
            ex.printStackTrace();
            session.getTransaction().rollback();
            result = null;
        }
        return result;
    }

    /**
     * Metodo que si encuentra un ejercicio (no desactivado) con el mismo
     * título lo devuelve, en caso contrario devuelve null
     * @param Ejercicios exer
     * @return Ejercicios
     */
    public Ejercicios search(Ejercicios exer) {
        Ejercicios resultado = new Ejercicios();
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        try {

            session.beginTransaction();

            //Consulta de busqueda por titulo y usuario
            resultado = (Ejercicios) session.createCriteria(Ejercicios.class).
                    add(Restrictions.eq("titulo", exer.getTitulo())).
                    add(Restrictions.ne("estados.idestado", (byte) 4)).
                    uniqueResult();

            session.getTransaction().commit();

        } catch (HibernateException err) {
            session.getTransaction().rollback();
            resultado = null;
        }
        return resultado;
    }

    /**
     * Metodo que si encuentra un ejercicio (no desactivado) con el mismo
     * id lo devuelve, en caso contrario devuelve null
     * @param Ejercicios exer
     * @return Ejercicios
     */
    public Ejercicios searchById(Ejercicios exer) {
        Ejercicios resultado = new Ejercicios();
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        try {


            session.beginTransaction();
            //Consulta de busqueda por titulo y usuario
            resultado = (Ejercicios) session.createCriteria(Ejercicios.class).
                    add(Restrictions.eq("idejercicio", exer.getIdejercicio())).
                    add(Restrictions.ne("estados.idestado", (byte) 4)).
                    uniqueResult();

            session.getTransaction().commit();

        } catch (HibernateException err) {
            session.getTransaction().rollback();
            resultado = null;
        }
        return resultado;
    }

    /**
     * Metodo que si encuentra ese ejercicio con estado "mandado" o
     * "elegido" devuelve true porque no se podrá eliminar ni editar el
     * ejercicio
     * @param Ejercicios exer
     * @return boolean
     */
    public boolean exerciseLock(Ejercicios exer) {
        boolean lock = false;
        List<Resueltos> resultado = null;
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();

        try {
            session.beginTransaction();
            resultado = session.createQuery("from Resueltos as r where r.ejercicios.idejercicio=" + exer.getIdejercicio() + "and ( r.estados.idestado=" + 9 + "or r.estados.idestado=" + 12 + ")").list();

            //Consulta de busqueda por titulo y usuario
           /*
             * resultado = (Resueltos) session.createCriteria(Resueltos.class).
             * add(Restrictions.eq("ejercicios.idejercicio",
             * exer.getIdejercicio())). add(Restrictions.eq("estados.idestado",
             * (byte) 9)). add(Restrictions.eq("estados.idestado", (byte) 12)).
             * uniqueResult();
             *
             * session.getTransaction().commit();
             */

        } catch (HibernateException err) {
            session.getTransaction().rollback();
            resultado = null;
        }
        if (!(resultado.isEmpty())) {
            lock = true;
        }
        return lock;
    }
    
    /**
     * La siguiente consulta nos mostrara el listado de ejercicios que
     * tiene un usuario pendiente de resolver
     * @param int idUser
     * @return List
     */
    public List listaEjercNoResueltos(int idUser) {
        List listEjNoResuelto = null;
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();

        try {
            session.beginTransaction();
            listEjNoResuelto = (List) session.createCriteria(Resueltos.class).
                    createAlias("usuarios", "us", CriteriaSpecification.LEFT_JOIN).
                    createAlias("ejercicios", "ej", CriteriaSpecification.LEFT_JOIN).
                    add(Restrictions.eq("estados.idestado", (byte) 12)).
                    add(Restrictions.eq("usuarios.idusuario", Integer.valueOf(idUser))).list();


            session.getTransaction().commit();
        } catch (HibernateException err) {
            System.out.println(err);

            session.getTransaction().rollback();
        }

        return listEjNoResuelto;
    }
    /**
     * Metodo que nos listara los ejercicios que
     * un usuario tiene pendiente de corregir
     * @param int idUser
     * @return List 
     */
    public List listaEjercNoCorregidos(int idUser) {
        List listEjNoCorregido = null;
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();

        try {
            session.beginTransaction();
            listEjNoCorregido = session.createCriteria(Resueltos.class).
                    createAlias("usuarios", "us", CriteriaSpecification.LEFT_JOIN).
                    createAlias("ejercicios", "ej", CriteriaSpecification.LEFT_JOIN).
                    add(Restrictions.eq("estados.idestado", (byte) 9)).
                    add(Restrictions.eq("ej.usuarios.idusuario", Integer.valueOf(idUser))).list();

            session.getTransaction().commit();

        } catch (HibernateException err) {
            System.out.println(err);

            session.getTransaction().rollback();
        }

        return listEjNoCorregido;
    }

    /**
     * Metodo que crea o actualizar un ejercicio y lo devuelve
     * @param Ejercicios exer
     * @return Ejercicios
     */
    public Ejercicios newOrUpdateExercise(Ejercicios exer) {
        Ejercicios resultado = new Ejercicios();
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        try {
            session.beginTransaction();
            session.saveOrUpdate(exer);
            session.getTransaction().commit();
            resultado = exer;
        } catch (HibernateException err) {
            session.getTransaction().rollback();
            resultado = null;
        }

        //Llamada a la funcion de Java Mail para autentificar al usuario
        return resultado;
    }

    /**
     * Metodo que devuelve la lista de ejercicios de un usuario con los datos de cada ejercicio
     * que no este en estado desactivo, null en caso contrario
     * @param Usuarios usuario
     * @return List 
     */
    public List<Ejercicios> listMyExercises(Usuarios usuario) {
        List<Ejercicios> resultado = null;
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        try {
            session.beginTransaction();
            resultado = session.createCriteria(Ejercicios.class).
                    createAlias("temas", "tem", CriteriaSpecification.LEFT_JOIN).
                    add(Restrictions.eq("usuarios.idusuario", usuario.getIdusuario())).
                    add(Restrictions.ne("estados.idestado", (byte) 4)).
                    addOrder(Order.desc("fecha")).list();

            session.getTransaction().commit();

        } catch (HibernateException err) {
            session.getTransaction().rollback();
            resultado = null;
        }
        return resultado;
    }

    /**
     * Metodo que devuelve true si ha conseguido eliminarlo (desactivar
     * ejercicio), false en otro caso
     * @param Ejercicios ejercicio
     * @return boolean
     */
    public boolean deleteExercise(Ejercicios ejercicio) {
        boolean lockExercise = exerciseLock(ejercicio);
        boolean exito = false;
        if (!lockExercise) {
            Ejercicios datosExer = searchById(ejercicio);
            Estados estadoNew = new Estados();
            estadoNew.setIdestado((byte) 4);
            datosExer.setEstados(estadoNew);

            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            try {
                session.beginTransaction();
                session.update(datosExer);
                session.getTransaction().commit();
                exito = true;

            } catch (HibernateException err) {
                session.getTransaction().rollback();
                exito = false;
            }
        }
        return exito;
    }
    /**
     * Metodo que actualiza el estado de un ejercicio resuelto a Corregido
     * @param Resueltos res 
     */
    public void corregido(Resueltos res) {

        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        try {
            Estados est = new Estados();
            est.setIdestado(Byte.valueOf("7"));
            res.setEstados(est);
            session.beginTransaction();
            session.update(res);
            session.getTransaction().commit();

        } catch (HibernateException err) {
            session.getTransaction().rollback();

        }

    }
}
